package main

import (
	"fmt"
	"go.manyji.com/lib/app"
	"go.manyji.com/lib/json"
	"go.manyji.com/lib/net/socks5"
	"go.manyji.com/sieve/pf"
	"io"
	"net/http"
	"net/url"
	"strings"
)

func main() {
	app.Start()
	pf.Run("facebook", query)
	app.Block()
}

func query(account string) (bool, error) {
	pp := pf.GetProxyPool("")
	proxy := pp.Get()
	if proxy == nil {
		return false, fmt.Errorf("no available proxy")
	}
	req := &Req{Account: account, data: map[string]string{}, proxy: proxy}
	defer func() {
		if req.proxy != nil { // step内判断proxy不可用就置为空，不返还
			pp.Put(req.proxy)
		}
	}()
	if err := req.Step1(); err != nil {
		return false, err
	}
	fmt.Println(req.data)
	if err := req.Step2(); err != nil {
		return false, err
	}
	fmt.Println(req.data)
	return req.Step3()
}

type Req struct {
	Account string
	data    map[string]string
	proxy   *socks5.Proxy
}

func (r *Req) Step1() error {
	resp, err := pf.Http(r.proxy).Get("https://www.facebook.com", func(req *http.Request) {
		addHeader(req)
	})
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("StatusCode %d", resp.StatusCode)
	}
	b, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	for _, c := range resp.Cookies() {
		r.data[c.Name] = c.Value
	}
	s := string(b)
	r.data["_js_datr"] = findJson(s, "_js_datr", true)
	r.data["jazoest"] = findInput(s, "jazoest")
	r.data["lsd"] = findInput(s, "lsd")
	r.data["__spin_r"] = findJson(s, "__spin_r", false)
	r.data["__spin_b"] = findJson(s, "__spin_b", true)
	r.data["__spin_t"] = findJson(s, "__spin_t", false)
	r.data["__hsi"] = findJson(s, "hsi", true)
	r.data["__hs"] = findJson(s, "haste_session", true)
	r.data["__rev"] = findJson(s, "client_revision", false)
	return nil
}

func (r *Req) Step2() error {
	u := "https://www.facebook.com/data/manifest/"
	resp, err := pf.Http(r.proxy).Get(u, func(req *http.Request) {
		addHeader(req)
		req.Header.Set("Referer", "https://www.facebook.com/")

		req.AddCookie(&http.Cookie{Name: "fr", Value: r.data["fr"]})
		req.AddCookie(&http.Cookie{Name: "sb", Value: r.data["sb"]})
		req.AddCookie(&http.Cookie{Name: "wd", Value: r.data["wd"]})
		req.AddCookie(&http.Cookie{Name: "_js_datr", Value: r.data["_js_datr"]})
	})
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("StatusCode %d", resp.StatusCode)
	}
	for _, c := range resp.Cookies() {
		r.data[c.Name] = c.Value
	}
	return nil
}

func (r *Req) Step3() (bool, error) {
	u := "https://www.facebook.com/ajax/login/help/identify.php?ctx=recover"
	data := url.Values{}
	data.Set("__a", "1")
	data.Set("__ccg", "GOOD")
	data.Set("__comet_req", "0")
	data.Set("__csr", "")
	data.Set("__dyn", "7xeUmwkHg7ebwKBWo5O12wAxu13wqovzEdEc8uxa0CEbo1nEhwem0nCq1ewcG0KEswaq0yE7i0n2US1vw4iwBgao884y0Mo5W3S7U2cxe0EUjwVw9O1iwKwHw8W1uwa-7U1bobodEGdw46wbS1bwzwqo2Ywmo")
	data.Set("__hs", r.data["__hs"])
	data.Set("__hsi", r.data["__hsi"])
	data.Set("__req", "1")
	data.Set("__rev", r.data["__rev"])
	data.Set("__s", "07tkun:fodsu0:9icci6")
	data.Set("__spin_b", r.data["__spin_b"])
	data.Set("__spin_r", r.data["__spin_r"])
	data.Set("__spin_t", r.data["__spin_t"])
	data.Set("__user", "0")
	data.Set("did_submit", "1")
	data.Set("dpr", "1")
	data.Set("email", r.Account)
	data.Set("jazoest", r.data["jazoest"])
	data.Set("lsd", r.data["lsd"])
	resp, err := pf.Http(r.proxy).Post(u, data,
		func(req *http.Request) {
			addHeader(req)
			req.Header.Set("Origin", "https://www.facebook.com")
			req.Header.Set("Referer", "https://www.facebook.com/login/identify/?ctx=recover&ars=facebook_login&from_login_screen=0")

			req.AddCookie(&http.Cookie{Name: "fr", Value: r.data["fr"]})
			req.AddCookie(&http.Cookie{Name: "sb", Value: r.data["sb"]})
			req.AddCookie(&http.Cookie{Name: "wd", Value: r.data["wd"]})
			req.AddCookie(&http.Cookie{Name: "datr", Value: r.data["datr"]})
		})
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return false, fmt.Errorf("StatusCode %d", resp.StatusCode)
	}

	b, err := io.ReadAll(resp.Body)
	if err != nil {
		return false, err
	}
	fmt.Println(resp.StatusCode, string(b))

	m := map[string]any{}
	if err := json.Unmarshal(b[9:], &m); err != nil {
		return false, err
	}
	// if _, ok := m["title"]; ok {
	// 	return true, nil
	// }
	// if _, ok := m["message"]; ok {
	// 	msg, o := m["message"].(string)
	// 	if !o {
	// 		return false, fmt.Errorf("message not found")
	// 	}
	// 	if strings.Contains(msg, "找不到用户") {
	// 		return false, nil
	// 	}
	// 	return true, nil
	// }
	for k, v := range m {
		fmt.Println(k, v)
	}
	return false, nil
}

func addHeader(req *http.Request) {
	req.Header.Set("Accept-Language", `zh-CN,zh;q=0.9`)
	req.Header.Set("sec-ch-ua", `"Google Chrome";v="111", "Not-A.Brand";v="8", "Chromium";v="111"`)
	req.Header.Set("sec-ch-ua-mobile", `?0`)
	req.Header.Set("sec-ch-ua-platform", `"Windows"`)
	req.Header.Set("Sec-Fetch-Dest", `empty`)
	req.Header.Set("Sec-Fetch-Mode", `cors`)
	req.Header.Set("Sec-Fetch-Site", `same-origin`)
	req.Header.Set("Sec-Fetch-User", `?1`)
	req.Header.Set("Upgrade-Insecure-Requests", `1`)
	req.Header.Set("User-Agent", `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36`)
	req.Header.Set("Keep-Alive", `600`)
	req.Header.Set("X-ASBD-ID", `198387`)
	req.Header.Set("X-FB-LSD", `AVr_RpI-H8U`)
}

func findJson(text, name string, isStr bool) string {
	key := `"` + name + `"`
	i := strings.LastIndex(text, key)
	if i < 0 {
		return ""
	}
	end := ","
	addlen := 1
	if isStr {
		end = `"`
		addlen = 2
	}
	text = text[i+len(key)+addlen:]
	i = strings.Index(text, end)
	if i < 0 {
		return ""
	}
	return text[:i]
}

func findInput(text, name string) string {
	key := `name="` + name + `" value="`
	i := strings.LastIndex(text, key)
	if i < 0 {
		return ""
	}
	text = text[i+len(key):]
	i = strings.Index(text, `"`)
	if i < 0 {
		return ""
	}
	return text[:i]
}
